import { PartSlaver } from './PartBase';
import { AppModel } from '../AppModel';
import { Stud } from '../Stud';
import { Usage } from '../StudUsage';
import { conn } from '@beshell/conn-ts/Connection';
import configServo from './config/servo.json'
import configMotor from './config/motor.json'

export abstract class MotorBase extends PartSlaver {

    constructor(_model: AppModel, json?: any){
        super(_model, json||configServo)
    }

    isValid(): boolean {
        return !!this.studs[0][0].bus && this.studs[0][0].bus.usage==Usage.pwm
    }

    pwmProvider(): Stud | null {
        if(!this.studs[0][0].bus) {
            return null
        }
        return this.studs[0][0].bus.findHostStud()
    }

    public abstract syncRemote(): void ;
    
    public isConnectionReady() {
        return !!this.pwmProvider()
    }
}


export class BeServo extends MotorBase {
    
    // 角度值(°) 0-360
    protected _position = 0
    get position() { return this._position }
    set position(p) {
        this._position = p
        this.syncRemote()
    }

    private _minPosition = 0
    public get minPosition() { return this._minPosition }
    public set minPosition(min) {
        this._minPosition = min
        
        if(this.position<this._minPosition)
            this.position = this._minPosition
    }

    private _maxPosition = 295
    public get maxPosition() { return this._maxPosition }
    public set maxPosition(max) {
        this._maxPosition = max
        this.syncRemoteMaxPos()

        if(this.position>this._maxPosition)
            this.position = this._maxPosition
    }

    public syncRemote() {
        if(!conn.isConnected)
            return
        let stud = this.pwmProvider()
        if(!stud)
            return
        conn.console.run(`${this.remoteVar()}.setValue(${this._position})`)
    }
    public syncRemoteMaxPos() {
        if(!conn.isConnected || !this.isConnectionReady())
            return
        conn.console.run(this.generateBeginCode())
    }
    
    public generateSetupCode(indent=0){
        return `${"\t".repeat(indent)}${this.remoteVar()} = new (require("besdk/driver/pwmservo")) (undefined, ${this.maxPosition})`
    }
    
    public generateBeginCode(indent=0){
        let stud = this.pwmProvider()
        if(!stud || !stud.gpio.name())
            return ''
        return `${"\t".repeat(indent)}${this.remoteVar()}.begin(${stud.gpio.name()}, ${this.maxPosition})`
    }
}

export class BeMotor extends MotorBase {

    constructor(_model: AppModel){
        super(_model, configMotor)
    }

    // 百分值(%) 0-1
    protected _velocity = 0
    get velocity() { return this._velocity }
    set velocity(v) {
        this._velocity = v
        this.syncRemote()
    }

    private _clockwise: boolean = true
    public get clockwise() { return this._clockwise }
    public set clockwise(c) {
        this._clockwise = c
        this.syncRemote()
    }

    public syncRemote() {
        if(!conn.isConnected)
            return
        conn.console.run(`${this.remoteVar()}.setValue(${this._velocity/100}, ${!this._clockwise})`)
    }

    public generateSetupCode(indent=0){
        return `${"\t".repeat(indent)}${this.remoteVar()} = new (require("besdk/driver/pwmmotor")) ()`
    }
    
    public generateBeginCode(indent=0){
        let stud = this.pwmProvider()
        if(!stud || !stud.gpio.name())
            return ''
        return `${"\t".repeat(indent)}${this.remoteVar()}.begin(${stud.gpio.name()})`
    }
}